﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Threading;
using vJine.Core;
using vJine.Lua.GUI.UI;

namespace vJine.Lua.GUI.BLL {
    public class AppGUI {
        LuaContext luaContext;
        RichTextBox rtbMessage;
        Dispatcher Dispatcher;
        public AppGUI(LuaContext luaContext, RichTextBox rtbMessage = null, Dispatcher Dispatcher = null) {
            this.luaContext = luaContext;

            this.rtbMessage = rtbMessage;
            this.Dispatcher = Dispatcher;

            Action on_clear = () => {
                this.message_clear();
            };
            this.luaContext.reg("on_clear", on_clear);

            Brush logBrush = new SolidColorBrush(Colors.DarkBlue);
            Action<string> on_log = (string log_msg) => {
                this.message_new("[日志]", log_msg, logBrush);
            };
            this.luaContext.reg("on_log", on_log);

            Brush debugBrush = new SolidColorBrush(Colors.Maroon);
            Action<string> on_debug = (string debug_msg) => {
                this.message_new("[调试]", debug_msg, debugBrush);
            };
            this.luaContext.reg("on_debug", on_debug);

            Brush warnBrush = new SolidColorBrush(Colors.DarkCyan);
            Action<string> on_warn = (string warn_msg) => {
                this.message_new("[警告]", warn_msg, warnBrush);
            };
            this.luaContext.reg("on_warn", on_warn);

            Brush errorBrush = new SolidColorBrush(Colors.OrangeRed);
            Action<string> on_error = (string err_msg) => {
                this.message_new("[错误]", err_msg, errorBrush);
            };
            this.luaContext.reg("on_error", on_error);

            //
            this.luaContext.reg("on_notify", new Call<Exec<string>, string, string>((string title, string initContent) => {
                Run rcontent = null;
                this.Dispatcher.Invoke((Action)delegate() {
                    Paragraph pNotify = new Paragraph();
                    pNotify.Inlines.Add(new Run(title + ":"));
                    rcontent = new Run(initContent);
                    pNotify.Inlines.Add(rcontent);
                    this.rtbMessage.Document.Blocks.Add(pNotify);
                    this.rtbMessage.ScrollToEnd();
                });
                return new Exec<string>((string content) => {
                    this.Dispatcher.Invoke((Action)delegate() {
                        rcontent.Text = content;
                    });
                });
            }));
            //
            this.luaContext.reg("on_graph", new Call<Exec<double, double[]>, string, string, double, ZedGraphViewer.YaxisConfig[]>((string graph_title, string x_title, double x_max, ZedGraphViewer.YaxisConfig[] yConfigs) => {
                ZedGraphViewer zgv = null;
                this.Dispatcher.Invoke((Action)delegate() {
                    zgv = new ZedGraphViewer();
                    zgv.init(graph_title, x_title, x_max, yConfigs);
                    Paragraph p = new Paragraph();
                    p.Inlines.Add(zgv);
                    this.rtbMessage.Document.Blocks.Add(p);
                    this.rtbMessage.ScrollToEnd();
                });
                return new Exec<double, double[]>((double x, double[] Ys) => {
                    lock (this) {
                        this.Dispatcher.Invoke((Action)delegate() {
                            zgv.update(x, Ys);
                        });
                    }
                });
            }));
            //
            this.luaContext.reg("on_graph_ber", new Call<Exec<string, double, double>, string, double, double>((string title, double x_min, double x_max) => {
                ZedGraphViewer zgv = null;
                this.Dispatcher.Invoke((Action)delegate() {
                    zgv = new ZedGraphViewer();
                    zgv.init_ber(title, x_min, x_max);
                    Paragraph p = new Paragraph();
                    p.Inlines.Add(zgv);
                    this.rtbMessage.Document.Blocks.Add(p);
                    this.rtbMessage.ScrollToEnd();
                });
                return new Exec<string, double, double>((string berTitle, double x, double y) => {
                    lock (this) {
                        this.Dispatcher.Invoke((Action)delegate() {
                            zgv.new_point(berTitle, x, y);
                        });
                    }
                });
            }));
        }

        public void SwitchPresentor(RichTextBox rtbMessage, Dispatcher Dispatcher) {
            lock (this) {
                this.rtbMessage = rtbMessage;
                this.Dispatcher = Dispatcher;
            }
        }

        void message_clear() {
            this.Dispatcher.BeginInvoke((Action)delegate() {
                this.rtbMessage.Document.Blocks.Clear();
            });
        }

        void message_new(string title, string message, Brush color) {
            lock (this) {
                message = title + " [" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "] " + message;
                this.Dispatcher.BeginInvoke((Action)delegate() {
                    this.rtbMessage.Document.Blocks.Add(new Paragraph(new Run(message) {
                        Foreground = color
                    }));
                    this.rtbMessage.ScrollToEnd();
                });
            }
        }
    }
}
